package com.leo.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.Entity;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class DaoBase implements Dao{
	@Resource
	protected HibernateTemplate hibernateTemplate;

	/**
	 * 增
	 * 
	 * @param entity
	 */
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void save(Object entity) {
		hibernateTemplate.save(entity);
	}

	/**
	 * 改
	 * 
	 * @param entity
	 */
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void update(Object entity) {
		hibernateTemplate.update(entity);
	}

	/**
	 * 删
	 * 
	 * @param entity
	 */
	@Override
	public void delete(Object entity) {
		hibernateTemplate.delete(entity);
	}

	/**
	 * 查
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 */
	@Override
	public <T> T findById(Class<T> entityClass, Object id) {
		// TODO Auto-generated method stub
		T o = hibernateTemplate.get(entityClass, (Serializable) id);
		return o;
	}

	/**
	 * 条件查询单个对象
	 * 
	 * @param entityClass
	 * @param whereSQL
	 * @param whereParams
	 * @return
	 */
	@Override
	public <T> T find(Class<T> entityClass, String whereSQL,
			Object ... whereParams) {
		// TODO Auto-generated method stub
		List<T> list = findAll(entityClass, whereSQL, 1, whereParams);
		if(list != null && list.size() > 0)
			return list.get(0);
		return null;
	}
	
	/**
	 * 条件查询全部对象
	 * 
	 * @param entityClass
	 * @param whereSQL
	 * @param whereParams
	 * @return
	 */
	@Override
	public <T> List<T> findAll(Class<T> entityClass, String whereSQL,
			Object ... whereParams){
		// TODO Auto-generated method stub
		return findAll(entityClass, whereSQL, -1, whereParams);
	}

	/**
	 * 条件查询多个对象
	 * 
	 * @param entityClass
	 * @param whereSQL
	 * @param whereParams
	 * @param maxResult 对象最大个数，-1为无限制
	 * @return
	 */
	@Override
	@SuppressWarnings("unchecked")
	public <T> List<T> findAll(Class<T> entityClass, String whereSQL, final int maxResult,
			final Object ... whereParams) {
		
		final String sql = "from " + getEntityName(entityClass) + (whereSQL == null ? "" :" where " + whereSQL);
		List<T> entitys = hibernateTemplate
				.executeFind(new HibernateCallback() {
					@Override
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(sql);
						setParams(query, whereParams, 0);
						if(maxResult != -1)
							query.setMaxResults(maxResult);
						List list = query.list();
						return list;
					}
				});
		
		return entitys;
	}
	
	@Override
	public <T> List<T> excuteQuery(String HQL,
			Object ... whereParams) {
		return excuteQuery(HQL,-1, whereParams);
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> List<T> excuteQuery(String HQL, final int maxResult,
			final Object ... whereParams) {

		final String sql = HQL;
		return hibernateTemplate.executeFind(new HibernateCallback() {
			@Override
			public List doInHibernate(Session session) throws HibernateException,
					SQLException {

				Query query = session.createQuery(sql);
				setParams(query, whereParams, 0);
				if(maxResult != -1)
					query.setMaxResults(maxResult);
				List list = query.list();
				return list;
			}
		});
		
	}

	/**
	 * 删除所有key字段在Params集合内的数据
	 * @param entityClass
	 * @param key 
	 * @param whereParams
	 */

	@Override
	@SuppressWarnings("unchecked")
	@Transactional(propagation=Propagation.REQUIRED)
	public <T> void delete(final Class<T> entityClass, final String key,
			final Object ... Params) {
		hibernateTemplate.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				final String sql = "delete from " + getEntityName(entityClass) + (key == null ? "" :" where " + key + " in (:plist)");
				Query query = session.createQuery(sql);
				if(Params != null && Params.length > 0)
					query.setParameterList("plist", Params);
				query.executeUpdate();
				return null;
			}
		});
	}

	/**
	 * 分页查询
	 * 
	 * @param entityClass
	 * @param whereSQL
	 * @param whereParams
	 * @param page 页号
	 * @param rows 每页最大行数
	 * @return
	 */
	@Override
	@SuppressWarnings("unchecked")
	public <T> List<T> getScrollData(final Class<T> entityClass,
			final String whereSQL,final int page, 
			final int rows, final Object ... whereParams) {
		return hibernateTemplate.executeFind(new HibernateCallback() {

			@Override
			public List<T> doInHibernate(Session session)
					throws HibernateException, SQLException {
				final String sql = "from " + getEntityName(entityClass) + (whereSQL == null ? "" :" where " + whereSQL);
				Query query = session.createQuery(sql);
				setParams(query, whereParams, 0);
				int _page = page;
				query.setFirstResult(_page*rows);
				query.setMaxResults(rows);
				return query.list();
			}
		});
	}

	@Override
	public <T> long getDataCount(Class<T> entityClass, String whereSQL,
			Object ... whereParams) {
		// TODO Auto-generated method stub
		final String sql = "select count(*) from " + getEntityName(entityClass) + (whereSQL == null ? "" :" where " + whereSQL);
		long count =  (Long)hibernateTemplate.find(sql, whereParams).get(0);
		return count;
	}

	/**
	 * 根据实体获取实体类名
	 * 
	 * @param <T>
	 * @param entityClass
	 * @return
	 */
	@Override
	public <T> String getEntityName(Class<T> entityClass) {
		String entityName = entityClass.getSimpleName();
		// 从注解中获取实体类名
		Entity entity = entityClass.getAnnotation(Entity.class);
		if (entity != null && !"".equals(entity.name())) {
			entityName = entity.name();
		}
		return entityName;
	}
	
	protected void setParams(Query sql, Object[] params,int startIndex) {
		if(params == null) return ;
		for(int i = 0; i < params.length; i++ ){
			sql.setParameter(i + startIndex, params[i]);
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void updateOrSave(Object entity) {
		// TODO Auto-generated method stub
		hibernateTemplate.merge(entity);
	}
}
